package cn.lxh.ymcc.service.impl;

import cn.lxh.ymcc.constants.CommonConstants;
import cn.lxh.ymcc.constants.LoginContant;
import cn.lxh.ymcc.constants.YmccError;
import cn.lxh.ymcc.domain.Login;
import cn.lxh.ymcc.domain.User;
import cn.lxh.ymcc.domain.UserAccount;
import cn.lxh.ymcc.domain.UserBaseInfo;
import cn.lxh.ymcc.dto.RedisRegisterDto;
import cn.lxh.ymcc.dto.RegisterDto;
import cn.lxh.ymcc.feign.LoginFeignClient;
import cn.lxh.ymcc.mapper.UserMapper;
import cn.lxh.ymcc.result.JSONResult;
import cn.lxh.ymcc.service.IUserAccountService;
import cn.lxh.ymcc.service.IUserBaseInfoService;
import cn.lxh.ymcc.service.IUserService;
import cn.lxh.ymcc.util.AssertUtil;
import cn.lxh.ymcc.util.BitStatesUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;

import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author small.tiger
 * @since 2022-07-15
 */

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    /**
     * 1.参数校验
     * 2.验证码是否正确
     * 3.手机号不能被注册
     * <p>
     * ==保存
     * 保存t_login
     * 。在service-uaa编写controller接口，调用service保存t_login数据
     * 。为service-uaa的controller编写Feign，给service-user调用
     * <p>
     * 保存user相关
     * 调用对应的service保存数据即可 t_user  t_user_base_info  t_user_account
     **/
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    private LoginFeignClient loginFeignClient;

    @Autowired
    private IUserBaseInfoService userBaseInfoService;
    @Autowired
    private IUserAccountService userAccountService;
    @Autowired
    private UserMapper userMapper;

    @Override
    /**
     * 加在方法上--开启
     */
    @GlobalTransactional
    public void register(RegisterDto dto) {
//* 1.参数校验
        String key = String.format(CommonConstants.REGISTER_PHONE_PRIFIX, dto.getMobile());
//* 2.验证码是否正确
        Object o = redisTemplate.opsForValue().get(key);

        AssertUtil.isNotNull(o, YmccError.USER_SMS_EMPTY.getMessage());

        RedisRegisterDto redisRegisterDto = (RedisRegisterDto) o;

        AssertUtil.isEquals(redisRegisterDto.getCode(), dto.getSmsCode(), "user两次验证码不一致");
//* 3.手机号不能被注册-查数据库--里面selectone加上条件

        User user = selectUserByPhone(dto.getMobile());

        AssertUtil.isNull(user, "user这个手机号码已近被注册过了");
//        需要自增id 于是需要一个万能对象
        JSONResult jsonResult = saveLogin(dto);
//        保存 成功
        AssertUtil.isTrue(jsonResult.isSuccess(), jsonResult.getMessage());
//* ==保存
//*  保存t_login---Data放一切对象
        AssertUtil.isNotNull(jsonResult.getData(), "登录信息保存失败！");
//*    。在service-uaa编写controller接口，调用service保存t_login数据
        Long loginId = Long.valueOf(jsonResult.getData().toString());
        user = saveUser(loginId, dto.getMobile());
        AssertUtil.isNotNull(user.getId(), "用户保存失败！！");
        //保存userBaseInfo
        initUserInfo(user.getId(), dto.getRegChannel());
        //保存userAccount
        initUserAccount(user.getId());
    }


    private User saveUser(Long loginId,String mobile) {
            User user = new User();
            user.setLoginId(loginId);
            user.setPhone(mobile);
            user.setNickName(mobile);
            long bitState =BitStatesUtils.OP_REGISTED;
//            long bitState = BitStatesUtils.addState(BitStatesUtils.OP_REGISTED, BitStatesUtils.OP_AUTHED_PHONE);


            user.setBitState(bitState);

            user.setCreateTime(System.currentTimeMillis());
            insert(user);
            return user;
        }
    private void initUserAccount(Long userId) {
        UserAccount account = new UserAccount();
        account.setId(userId);
        account.setCreateTime(System.currentTimeMillis());
        userAccountService.insert(account);
    }

    private void initUserInfo(Long userId, String regChannel) {
        UserBaseInfo info = new UserBaseInfo();
        info.setId(userId);
        info.setCreateTime(System.currentTimeMillis());
        info.setRegChannel(regChannel);//注册渠道
        userBaseInfoService.insert(info);
    }

    /**
     * user表的保存 要自增id
     * @param dto
     */
    private JSONResult saveLogin(RegisterDto dto) {
        Login login = new Login();
        login.setUsername(dto.getMobile());
        login.setPassword(dto.getPassword());
        login.setType(LoginContant.User_TYpe_NORMAL);
        return loginFeignClient.save(login);
    }

    /**
     * 查找这个人是不是已近被注册了
     * @param mobile
     * @return
     */
    private User selectUserByPhone(String mobile) {
        Wrapper<User> tWrapper = new EntityWrapper();
        tWrapper.eq("phone",mobile);
        return selectOne(tWrapper);
    }

    /**
     * 黑名单
     * @param
     * @return
     */

    @Override
    public List<User> backpageByState(Long bitState) {
        Wrapper<User> tWrapper = new EntityWrapper();
        tWrapper.ge("bit_state",1);
        return userMapper.selectList(tWrapper);
    }

    /**
     * 拉黑用户
     * @param id
     */
    @Override
    public void backuser(Long id) {
        User user = userMapper.selectById(id);

        user.setBitState(0L);
        userMapper.updateById(user);
    }

    @Override
    public List<User> whitepagelist(Long bitState) {
        Wrapper<User> tWrapper = new EntityWrapper();
        tWrapper.lt("bit_state",1);
        return userMapper.selectList(tWrapper);
    }

    /**
     * 拉白用户
     * @param id
     */
    @Override
    public void whiteuser(Long id) {
        User user = userMapper.selectById(id);
        user.setBitState(1L);
        userMapper.updateById(user);
    }

    /**
     * 根据电话查询
     * @param phone
     * @return
     */
    @Override
    public User selectByPhone(String phone) {

        return userMapper.selectByPhone(phone);
    }
}
